tree grammar DecluseInterpreter;

options {
    tokenVocab=Calc;                    // import tokens from Calc.tokens
    ASTLabelType=CommonTree;            // AST nodes are of type CommonTree
}

@header {
package vb.week3.calc;
import java.util.Map;
import java.util.HashMap;
import java.lang.*;
}

@members { 
    private Map<String,Integer> store = new HashMap<String,Integer>();   
}

program
    :   ^(PROGRAM (declaration | statement)+)
    ;
    
declaration
    :   ^(VAR id=IDENTIFIER type)
            { store.put($id.text, 0); } 
    ;

statement 
    :   ^(BECOMES id=IDENTIFIER v=expr)
            { store.put($id.text, v);       }
    |   ^(PRINT v=expr)
            { System.out.println("" + v);   }
    |   ^(SWAP x=IDENTIFIER y=IDENTIFIER){   
            
            int temp = store.get($x.text);
            store.put($x.text,store.get($y.text));
            store.put($y.text,temp);
            }
    ;
    
expr returns [int val = 0;] 
    :   v=expr2                  { val = v; } 
    |   ^(PLUS x=expr y=expr2)   { val = x + y;  }
    |   ^(MINUS x=expr y=expr2)  { val = x - y;  }
    |   ^(IF x=expr y=expr z=expr)  {if(x!=0){val = y;} else{val = z;}}
    ;
        
expr2 returns [int val = 0;] 
    :   z=operand                     { val = z;      }
    |   ^(TIMES x=expr2 y=operand)    { val = x * y;  }
    |   ^(DIVIDEBY x=expr2 y=operand) {
                                        if(y == 0)
                                          throw new IllegalArgumentException("Divide by zero not allowed");
                                        val = x / y;
                                      }
    ;
    
operand returns [int val = 0]
    :   id=IDENTIFIER   { val = store.get($id.text);       } 
    |   n=NUMBER        { val = Integer.parseInt($n.text); }
    ;
    
type
    :   INTEGER
    ;
